package kylin.base.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import kylin.base.entity.DataTables;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Repository;


@Repository("baseDaoImpl")
public class BaseDaoImpl<T> implements BaseDao<T>{

	@Autowired
	public HibernateTemplate hibernateTemplate;

	/**
	 * <p>Methods : setQueryParams</P>
	 * <p>Description : 动态设置参数</p>
	 * @Date : 2015年9月18日 上午11:49:19
	 * @param session
	 * @param hql
	 * @param params
	 * @return 返回查询对象
	 */
	private Query setQueryParams(Session session,String hql, Object ... params) {
		Query query = session.createQuery(hql);
		for (int i = 0; i < params.length; i++) {
			query.setParameter(i, params[i]);
		}
		return query;
	}

	/**
	 * <p>Methods : getEntityClass</P>
	 * <p>Description : 获取泛型中的实体类型</p>
	 * @Date : 2015年9月18日 上午11:42:01
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected Class<T> getEntityClass(){
		return (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	/**
	 * <p>Methods : getEntityClassName</P>
	 * <p>Description : 获取实体类型名</p>
	 * @Date : 2015年9月18日 上午11:43:43
	 * @return
	 */
	protected String getEntityClassName() {
		ClassMetadata meta = hibernateTemplate.getSessionFactory().getClassMetadata(this.getEntityClass());
		return meta.getEntityName();
	}

	/**
	 * <p>Methods : executeUpdate</P>
	 * <p>Description : 执行增、删、改等操作</p>
	 * @Date : 2015年9月18日 上午11:47:55
	 * @param hql
	 * @param params
	 */
	protected Integer executeUpdate(final String hql, final Object ... params){
		return hibernateTemplate.execute(new HibernateCallback<Integer>() {
			@Override
			public Integer doInHibernate(Session session) throws HibernateException {
				Query createQuery = setQueryParams(session, hql, params);
				return createQuery.executeUpdate();
			}
		});
	}

	/**
	 * <p>Methods : executeQuery</P>
	 * <p>Description : 执行查询操作</p>
	 * @Date : 2015年9月18日 下午1:05:25
	 * @param hql
	 * @param params
	 * @return
	 */
	protected List<T> executeQuery(final String hql, final Object ... params){
		return hibernateTemplate.execute(new HibernateCallback<List<T>>() {
			@Override
			@SuppressWarnings("unchecked")
			public List<T> doInHibernate(Session session) throws HibernateException {
				Query createQuery = setQueryParams(session, hql, params);
				return (List<T>)createQuery.list();
			}
		});
	}

	/**
	 * <p>Methods : getSession</P>
	 * <p>Description : 获取Session</p>
	 * @Date : 2015年9月18日 下午1:13:19
	 * @return
	 */
	public Session getSession(){
		return hibernateTemplate.getSessionFactory().getCurrentSession();
	}

	/**
	 * <p>Methods : getPkColunmName</P>
	 * <p>Description : 获取主键名</p>
	 * @Date : 2015年9月18日 上午11:45:45
	 * @return
	 */
	public String getPKColunmName(){
		ClassMetadata meta = hibernateTemplate.getSessionFactory().getClassMetadata(getEntityClass());
		return meta.getIdentifierPropertyName();
	}

	/**
	 * <p>Methods : insert</P>
	 * <p>Description : 保存实体</p>
	 * @Date : 2015年9月18日 上午11:46:26
	 * @param entity
	 */
	public void insert(T entity){
		hibernateTemplate.save(entity);
	}

	/**
	 * <p>Methods : update</P>
	 * <p>Description : 更新实体</p>
	 * @Date : 2015年9月18日 上午11:46:42
	 * @param entity
	 */
	public void update(T entity){
		hibernateTemplate.update(entity);
	}

	/**
	 * <p>Method Name : saveOrUpdate</p>
	 * <p>Method Desc : 保存或更新</p>
	 * <p>Date : 2015-11-6 下午6:37:01</p>
	 * <p>Author : XQL</p>
	 * @param entity
	 */
	public void saveOrUpdate(T entity){
		hibernateTemplate.saveOrUpdate(entity);
	}

	/**
	 * <p>Methods : delete</P>
	 * <p>Description : 删除实体</p>
	 * @Date : 2015年9月18日 上午11:46:52
	 * @param entity
	 */
	public void delete(T entity){
		hibernateTemplate.delete(entity);
	}

	/**
	 * <p>Methods : deleteById</P>
	 * <p>Description : 根据主键删除数据</p>
	 * @Date : 2015年9月18日 上午11:47:16
	 * @param id
	 * @throws Exception
	 */
	public void deleteById(Serializable id){
		String hql = "delete " + this.getEntityClassName() + " where " + this.getPKColunmName() + " = ?";
		this.executeUpdate(hql,id);
	}

	/**
	 * <p>Methods : deleteByIds</P>
	 * <p>Description : 根据主键批量删除数据</p>
	 * @Date : 2015年9月18日 下午1:34:23
	 * @param idList
	 */
	public void deleteByIds(List<Object> idList){
		hibernateTemplate.deleteAll(this.findByIdList(idList));
	}

	/**
	 * <p>Method Name : executeHQL</p>
	 * <p>Method Desc : 执行HQL语句[增、删、改]</p>
	 * @Date 2015年9月19日 下午6:23:33
	 * @Author XQL
	 * @param hql
	 * @param params
	 * @return
	 */
	public boolean executeHQL(String hql,Object ... params){
		Integer num = this.executeUpdate(hql, params);
		return num <=0 ? false : true;
	}

	/**
	 * <p>Methods : get</P>
	 * <p>Description : 根据主键查询实体</p>
	 * @Date : 2015年9月18日 上午11:52:47
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public T get(Serializable id) {
		return (T)hibernateTemplate.get(this.getEntityClassName(), id);
	}

	/**
	 * <p>Method Name : findByIdList</p>
	 * <p>Method Desc : 主键list集合条件查询多条数据</p>
	 * @Date 2015年9月19日 下午4:49:05
	 * @Author XQL
	 * @param idList
	 * @return
	 */
	public List<T> findByIdList(final List<Object> idList){
		if(idList == null || idList.size() <= 0){
			return null;
		}else{

			final String hql = "from " + this.getEntityClassName() + " where " + this.getPKColunmName() + " in (:idList)";

			return hibernateTemplate.execute(new HibernateCallback<List<T>>() {
				@Override
				@SuppressWarnings("unchecked")
				public List<T> doInHibernate(Session session) throws HibernateException {

					Query query = session.createQuery(hql);
					query.setParameterList("idList", idList);

					return (List<T>)query.list();
				}
			});
		}
	}

	/**
	 * <p>Methods : findByAll</P>
	 * <p>Description : 查询所有数据</p>
	 * @Date : 2015年9月18日 下午1:06:14
	 * @return
	 * @throws Exception
	 */
	public List<T> findByAll(){
		String hql = "from " + this.getEntityClassName();
		return this.executeQuery(hql);
	}

	/**
	 * <p>Method Name : findByEntity</p>
	 * <p>Method Desc : 根据实体查询数据</p>
	 * @Date 2015年9月19日 下午1:05:24
	 * @Author XQL
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByEntity(final T entity){
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(entity.getClass()).add(Example.create(entity));
		return (List<T>)hibernateTemplate.findByCriteria(detachedCriteria);
	}

	/**
	 * <p>Method Name : findByHQL</p>
	 * <p>Method Desc : 通用HQL查询全部数据</p>
	 * @Date 2015年9月19日 下午1:22:31
	 * @Author XQL
	 * @param hql
	 * @param params
	 * @return
	 */
	public List<T> findByHQL(final String hql,final Object ... params){
		return this.executeQuery(hql, params);
	}

	/**
	 * <p>Method Name : findByHQL</p>
	 * <p>Method Desc : 通用HQL查询部分数据</p>
	 * @Date 2015年9月19日 下午1:39:50
	 * @Author XQL
	 * @param start
	 * @param length
	 * @param hql
	 * @param params
	 * @return
	 */
	public List<T> findByHQL(final int start,final int length,final String hql,final Object ... params){
		return hibernateTemplate.execute(new HibernateCallback<List<T>>() {
			@SuppressWarnings("unchecked")
			public List<T> doInHibernate(Session session) throws HibernateException {
				Query query = setQueryParams(session, hql, params);
				return query.setFirstResult(start).setMaxResults(length).list();
			}
		});
	}

	/**
	 *  <p>Description : 通用HQL查询全部数据,不指定List对象</p>
	 * <p>Author : XQL</p>
	 * <p>Date : 2016/1/30 15:34</p>
	 *
	 * @param hql hql语句
	 * @param params 参数
     * @return
     */
	public Object find4Object(final String hql, final Object... params){
		return hibernateTemplate.execute(new HibernateCallback<Object>() {
			@Override
			@SuppressWarnings("unchecked")
			public Object doInHibernate(Session session) throws HibernateException {
				Query createQuery = setQueryParams(session, hql, params);
				return createQuery.list();
			}
		});
	}

	/**
	 * <p>Method Name : findByCount</p>
	 * <p>Method Desc : 查询总记录数据</p>
	 * @Date 2015年9月19日 下午5:49:37
	 * @Author XQL
	 * @param hql 可以为null，为null时默认无条件查询总条数
	 * @param params
	 * @return
	 */
	public int findByCount(String hql,final Object ... params){
		if(hql == null){
			hql = "select count(" + this.getPKColunmName() + ")from "+this.getEntityClassName();
		}

		Query query = this.setQueryParams(this.getSession(), hql, params);

		return ((Long)query.uniqueResult()).intValue();

	}

	/**
	 * <p>Methods : findByPage</P>
	 * <p>Description : 通用HQL分页查询返回DataTables对象</p>
	 * @Date : 2015年9月10日 下午1:55:18
	 * @param hql HQL语句
	 * @param dt DataTables对象
	 * @param params HQL语句参数集
	 * @return
	 */
	public void findByPage(String hql, DataTables dt,Object... params) {

		Query query = this.getSession().createQuery(hql);
		Query queryCount = this.getSession().createQuery("select count(*) " + hql);
		if(params != null && params.length>0){
			for(int i=0;i<params.length;i++){
				query.setString(i, params[i].toString());
				queryCount.setString(i, params[i].toString());
			}
		}

		int count = ((Long)(queryCount.uniqueResult())).intValue();

		@SuppressWarnings("unchecked")
		List<T> list = query.setFirstResult(dt.getStart()).setMaxResults(dt.getLength()).setCacheable(true).list();

		dt.setRecordsTotal(count);
		dt.setRecordsFiltered(count);

		dt.setData(list);
	}
}
